<!doctype html>
<!--
@license
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
  <meta charset="utf-8">
  <script src="../../node_modules/@webcomponents/webcomponentsjs/webcomponents-bundle.js"></script>
  <script src="wct-browser-config.js"></script>
  <script src="../../node_modules/wct-browser-legacy/browser.js"></script>
  <script type="module" src="../../polymer-legacy.js"></script>
  <script type="module" src="./custom-style-import.js"></script>
</head>
<body>
  <!-- FIXME(polymer-modulizer):
        These imperative modules that innerHTML your HTML are
        a hacky way to be sure that any mixins in included style
        modules are ready before any elements that reference them are
        instantiated, otherwise the CSS @apply mixin polyfill won't be
        able to expand the underlying CSS custom properties.
        See: https://github.com/Polymer/polymer-modulizer/issues/154
        -->
    <script type="module">
const $_documentContainer = document.createElement('template');

$_documentContainer.innerHTML = `<custom-style>
  <style is="custom-style">
    x-bar {
      border: 1px solid red;
      display: block;
    }

    html {
      --bag2: {
        border: 12px solid beige;
      };
    }

    html {
      --red-text : {
        color : red;
      };
    }

    html{--blue-text:{color:#0000ff};--dummy-mixin:{};--bold-text:{font-weight:700}}


    html {

      --italic: italic;

      --bag: {
        margin: 1px;
        border: 1px solid black;
      };

      /* mocha.css in the testing environment is hosing this test;
      use !important as a workaround */
      margin: 10px !important;
      width: auto;

      --special: var(--primary);

      --after: 11px solid orange;
      @apply --bag2;
    }

    x-foo {

      --primary: 10px;
      --x-foo-more: 6px solid orange;
    }
  </style>
</custom-style>`;

document.body.appendChild($_documentContainer.content);
</script>
  <script type="module">
const $_documentContainer = document.createElement('template');

$_documentContainer.innerHTML = `<custom-style>
  <style is="custom-style">
    .bag {
      ;@apply --bag;
    }

    .italic {
      font-style: var(--italic);
    }

    .import-mixin {
      @apply --import-mixin;
    }

    .import-var {
      border: var(--import-var);
    }

    .dynamic {
      border: var(--dynamic);
    }

    #after::after {
      content: 'after';
      border: var(--after);
    }
  </style>
</custom-style>`;

document.body.appendChild($_documentContainer.content);
</script>

<script type="module">
const $_documentContainer = document.createElement('template');

$_documentContainer.innerHTML = `<custom-style>
  <style is="custom-style" include="shared-style2">
    .zazz {
      border: 20px solid blue;
    }
  </style>
  <style>
    .foo--bar {
      border-top : 3px solid red;
    }
  </style>
</custom-style>`;

document.body.appendChild($_documentContainer.content);
</script>
<script type="module">
const $_documentContainer = document.createElement('template');

$_documentContainer.innerHTML = `<custom-style>
  <style is="custom-style">
    @media (min-width: 1px) {
      .foo--bar {
        border-top : 20px solid blue;
      }
    }
  </style>
</custom-style>`;

document.body.appendChild($_documentContainer.content);
</script>
  <script type="module">
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `<div class="italic">italic</div>`;
document.body.appendChild($_documentContainer.content);
</script>
  <script type="module">
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `<div class="bag">bag</div>`;
document.body.appendChild($_documentContainer.content);
</script>
  <script type="module">
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `<div class="mix">mix</div>`;
document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `<div class="dynamic">dynamic</div>`;
document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `<div class="import-mixin">import-mixin</div>`;
document.body.appendChild($_documentContainer.content);
</script>
  <script type="module">
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `<div class="import-var">import-var</div>`;
document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `<x-bar></x-bar>`;
document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `<x-foo></x-foo>`;
document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `<x-red-text></x-red-text>`;
document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `<x-blue-bold-text></x-blue-bold-text>`;
document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `<parent-variable-with-var></parent-variable-with-var>`;
document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `<br>`;
document.body.appendChild($_documentContainer.content);
</script><script type="module">
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `<br>`;
document.body.appendChild($_documentContainer.content);
</script>
  <script type="module">
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `<div id="after"></div>`;
document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `<div class="foo"></div>`;
document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');
$_documentContainer.innerHTML = `<div class="foo--bar"></div>`;
document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');

$_documentContainer.innerHTML = `<dom-module id="x-baz">
    <template>
    <style>
      :host {
        display: block;
      }
    </style>
      <div id="me">x-baz</div>
    </template>
  </dom-module>`;

document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');

$_documentContainer.innerHTML = `<dom-module id="x-bar">
    <template>
    <style>
      :host {
        display: block;
      }
    </style>
      <div>x-bar</div>
      <x-baz id="baz"></x-baz>
    </template>
  </dom-module>`;

document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');

$_documentContainer.innerHTML = `<dom-module id="x-foo">
    <template>
    <style>
      :host {
        display: block;
        border: solid tomato;
        border-width: var(--special);
      }

      div {
        @apply --bag;
      }

      #more {
        border: var(--x-foo-more);
      }
    </style>
      <div id="me">x-foo</div>
      <x-bar id="bar1"></x-bar>
      <x-bar id="bar2"></x-bar>
      <x-bar id="bar3"></x-bar>
      <div id="more">deep</div>
    </template>
  </dom-module>`;

document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');

$_documentContainer.innerHTML = `<dom-module id="x-red-text">
    <template>
    <style>
      :host {
        @apply --red-text;
      }
    </style>
      x-red-text
    </template>
  </dom-module>`;

document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');

$_documentContainer.innerHTML = `<dom-module id="x-blue-bold-text">
    <template>
    <style>
      :host {@apply --blue-text;@apply --bold-text;}
    </style>
      x-blue-bold-text
    </template>
  </dom-module>`;

document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');

$_documentContainer.innerHTML = `<dom-module id="parent-variable-with-var">
    <template>
      <style>
        child-variable-with-var {
          --variable-property-own-line: 1px;
          --variable-property-preceded-property: 2px;
          --variable-property-before-property: yellow;
          --variable-property-after-property: 3px;
          --variable-property-after-assignment: 4px;
          --variable-property-before-assignment: 5px;
          --variable-into-first-variable: 9px;
          --variable-into-second-variable: 10px;
          --variable-into-third-variable: 11px;
        }
      </style>
      <child-variable-with-var id="child"></child-variable-with-var>
    </template>
  </dom-module>`;

document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');

$_documentContainer.innerHTML = `<dom-module id="child-variable-with-var">
    <template>
      <style>
        child-of-child-with-var {
          /* in certain browsers (e.g. Safari) \`top\`, \`bottom\`, \`left\`, \`right\` don't compute
             when no explicit position is defined (\`relative\` / \`absolute\` / \`fixed\`) */
          position: relative;
          --variable-own-line: "Varela font";
          margin-top: var(--variable-property-own-line);
          margin-bottom: var(--variable-property-preceded-property);
          --variable-between-properties: 6px;
          background-color: var(--variable-property-before-property); padding-top: var(--variable-property-after-property);
          --variable-assignment-before-property: 7px; padding-bottom: var(--variable-property-after-assignment);
          padding-left: var(--variable-property-before-assignment);--variable-assignment-after-property: 8px;
          top: 12px;--variable-from-other-variable: var(--variable-into-first-variable);--variable-from-another-variable: var(--variable-into-second-variable); --variable-from-last-variable: var(--variable-into-third-variable);
          height: 20px;
        }
      </style>
      <child-of-child-with-var id="child"></child-of-child-with-var>
    </template>
  </dom-module>`;

document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
const $_documentContainer = document.createElement('template');

$_documentContainer.innerHTML = `<dom-module id="child-of-child-with-var">
    <template>
      <style>
        :host {
          font-family: var(--variable-own-line);
          padding-right: var(--variable-between-properties);
          margin-left: var(--variable-assignment-before-property);
          margin-right: var(--variable-assignment-after-property);
          bottom: var(--variable-from-other-variable);
          left: var(--variable-from-another-variable);
          right: var(--variable-from-last-variable);
        }
      </style>
      Text
    </template>
  </dom-module>`;

document.body.appendChild($_documentContainer.content);
</script>

  <script type="module">
import './custom-style-import.js';
import { Polymer } from '../../lib/legacy/polymer-fn.js';
Polymer({
  is: 'x-baz'
});

Polymer({
  is: 'x-bar'
});

Polymer({
  is: 'x-foo'
});

Polymer({
  is: 'x-red-text'
});

Polymer({
  is: 'x-blue-bold-text'
});
</script>

  <script type="module">
import './custom-style-import.js';
import { updateStyles } from '../../lib/mixins/element-mixin.js';
import { Polymer } from '../../lib/legacy/polymer-fn.js';

suite('custom-style', function() {

  var xBar, xFoo, stylesBuilt;

  suiteSetup(function() {
    xBar = document.querySelector('x-bar');
    xFoo = document.querySelector('x-foo');
  });

  test('root styles applied', function() {
    assertComputed(xBar, '1px');
  });

  test('root styles have lower bound encapsulation', function() {
    assertComputed(xFoo.$.bar1, '0px');
  });

  test('custom properties registered as defaults', function() {
    var propsToCheck = ['--italic'];
    if (!window.ShadyCSS || ShadyCSS.nativeCss || stylesBuilt) {
      var sep = window.ShadyCSS.ApplyShim._separator;
      propsToCheck.push('--bag' + sep + 'margin', '--bag' + sep + 'border');
    } else {
      propsToCheck.push('--bag');
    }
    if (!window.ShadyCSS || ShadyCSS.nativeCss) {
      var cs = getComputedStyle(document.documentElement);
      propsToCheck.forEach(function(p) {
        assert.ok(cs.getPropertyValue(p));
      });
    } else {
      propsToCheck.forEach(function(p) {
        assert.ok(ShadyCSS.ScopingShim.getComputedStyleValue(document.documentElement, p));
      });
    }
  });

  test('custom properties with space before semicolon', function() {
    var red = document.querySelector('x-red-text');
    assertComputed(red, 'rgb(255, 0, 0)', 'color');
  });

  test('custom properties in minified css', function() {
    var blue = document.querySelector('x-blue-bold-text');
    assertComputed(blue, 'rgb(0, 0, 255)', 'color');

    var computed = getComputedStyle(blue);
    // Firefox returns `700`, while Chrome returns original `bold`
    assert.ok(computed.fontWeight == '700' || computed.fontWeight == 'bold', 'computed style incorrect for fontWeight');
  });

  test('custom-styles apply normal and property values to main document', function() {
    var bag = document.querySelector('.bag');
    var italic = document.querySelector('.italic');
    assertComputed(bag, '1px');
    assertComputed(italic, 'italic', 'font-style');
  });

  test('imported custom-styles apply', function() {
    if (stylesBuilt && window.ShadyCSS && !ShadyCSS.nativeCss) {
      // css build will test this by using vulcanize.
      // this inlines the custom-style after the consumption point, and changes the timing for custom property shim
      // Force an update style for this weird corner case in the tests
      updateStyles();
    }
    var v = document.querySelector('.import-var');
    var m = document.querySelector('.import-mixin');
    assertComputed(v, '3px');
    assertComputed(m, '4px');
  });

  test('dynamic custom-styles apply', function() {
    var dynamic = document.querySelector('.dynamic');
    assertComputed(dynamic, '0px');
    var cs = document.createElement('custom-style');
    var s = document.createElement('style');
    s.textContent = ':root { --dynamic: 11px solid orange; }';
    cs.appendChild(s);
    document.body.appendChild(cs);
    updateStyles();
    assertComputed(dynamic, '11px');
  });

  test('custom-styles apply normal and property values to elements and cannot be late bound via inheritance', function() {
    var e = document.querySelector('x-foo').$.me;
    assertComputed(e, '1px');
  });

  test('custom-styles apply to pseudo elements', function() {
    var e = document.querySelector('#after');
    assertComputed(e, '11px', null, '::after');
  });

  test('style paths in included dom-modules loaded in import', function() {
    var foo = document.querySelector('.foo');
    var url = getComputedStyle(foo).backgroundImage;
    assert.include(url, 'sub/google.png');
  });

  test('style paths can have arbitrary whitespace', function() {
    var foo = document.querySelector('.foo');
    assertComputed(foo, '4px', 'width');
  });

  test('imperative custom style', function() {
    var cs = document.createElement('custom-style');
    var style = document.createElement('style');
    style.textContent = '.zonk { border: 13px solid tomato;}';
    cs.appendChild(style);
    var d = document.createElement('div');
    d.classList.add('zonk');
    document.body.appendChild(d);
    document.body.appendChild(cs);
    updateStyles();
    if (window.ShadyDOM) {
      assert.ok(style.textContent.match(':not'));
    }
    assertComputed(d, '13px');
    document.body.removeChild(d);
    document.body.removeChild(cs);

  });

  test('imperative custom style with include', function() {
    var cs = document.createElement('custom-style');
    var style = document.createElement('style');
    style.setAttribute('include', 'shared-style2');
    cs.appendChild(style);
    var d = document.createElement('div');
    d.classList.add('zazz');
    document.body.appendChild(d);
    document.body.appendChild(cs);
    updateStyles();
    assertComputed(d, '16px');
    document.body.removeChild(d);
    document.body.removeChild(cs);
  });

  test('imperative custom style with non-existent include', function() {
    var s1 = document.createElement('custom-style');
    var style = document.createElement('style');
    s1.appendChild(style);
    style.setAttribute('include', 'does-not-exist');
    style.textContent = '.ziz { border: 14px solid tomato;}';
    var d = document.createElement('div');
    d.classList.add('ziz');
    document.body.appendChild(d);
    document.body.appendChild(s1);
    updateStyles();
    assertComputed(d, '14px');
    document.body.removeChild(d);
    document.body.removeChild(s1);
  });

  test('include style data applied before textContent', function() {
    var d = document.createElement('div');
    d.classList.add('zazz');
    document.body.appendChild(d);
    assertComputed(d, '20px');
    document.body.removeChild(d);
  });

  test('variable name with assignment including var correctly applied', function() {
    Polymer({
      is: 'parent-variable-with-var'
    });
    Polymer({
      is: 'child-variable-with-var'
    });
    Polymer({
      is: 'child-of-child-with-var'
    });

    var d = document.querySelector('parent-variable-with-var');
    var el = d.$.child.$.child;
    assertComputed(el, '1px', 'margin-top');
    assertComputed(el, '2px', 'margin-bottom');
    assertComputed(el, '3px', 'padding-top');
    assertComputed(el, '4px', 'padding-bottom');
    assertComputed(el, '5px', 'padding-left');
    assertComputed(el, '6px', 'padding-right');
    assertComputed(el, '7px', 'margin-left');
    assertComputed(el, '8px', 'margin-right');
    assertComputed(el, 'rgb(255, 255, 0)', 'background-color');
    assertComputed(el, '9px', 'bottom');
    assertComputed(el, '10px', 'left');
    assertComputed(el, '11px', 'right');
    assertComputed(el, '12px', 'top');

    // Avoid Edge bug with CSS Custom Properties and Fonts.
    if (navigator.userAgent.match('Edge') && (!window.ShadyCSS || window.ShadyCSS.nativeCss)) {
      return;
    }

    // Because FireFox and Chrome parse font-family differently...
    var computed = getComputedStyle(el);
    assert.equal(computed['font-family'].replace(/['"]+/g, ''), 'Varela font');
  });

  test('BEM-like CSS selectors under media queries', function() {
    assertComputed(document.querySelector('.foo--bar'), '20px');
  });

});


function assertComputed(element, value, property, pseudo) {
  var computed = getComputedStyle(element, pseudo);
  property = property || 'border-top-width';
  assert.equal(computed[property], value, 'computed style incorrect for ' + property);
}
</script>

</body>
</html>
